package com.zenithmind.library.controller;

import com.zenithmind.common.result.PageResult;
import com.zenithmind.common.result.Result;
import com.zenithmind.library.controller.base.BaseLibraryController;
import com.zenithmind.library.pojo.dto.AuthorCreateDTO;
import com.zenithmind.library.pojo.dto.AuthorUpdateDTO;
import com.zenithmind.library.pojo.query.AuthorQuery;
import com.zenithmind.library.pojo.vo.AuthorVO;
import com.zenithmind.library.service.AuthorQueryService;
import com.zenithmind.library.service.AuthorManagementService;
import com.zenithmind.library.service.AuthorImportExportService;
import com.zenithmind.library.service.AuthorStatisticsService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * 作者管理控制器
 * 遵循单一职责原则：只负责HTTP请求处理，不包含业务逻辑
 * 遵循依赖倒置原则：依赖抽象接口而不是具体实现
 *
 * @author ZenithMind
 * @since 2024-06-14
 */
@Slf4j
@RestController
@RequestMapping("/api/zenithMind/v1/authors")
@RequiredArgsConstructor
@Tag(name = "作者管理", description = "作者信息的增删改查操作")
public class AuthorController extends BaseLibraryController {

    // 依赖抽象接口，遵循依赖倒置原则
    private final AuthorQueryService authorQueryService;
    private final AuthorManagementService authorManagementService;
    private final AuthorImportExportService authorImportExportService;
    private final AuthorStatisticsService authorStatisticsService;

    @GetMapping
    @Operation(summary = "分页查询作者", description = "根据条件分页查询作者列表")
    @PreAuthorize("hasAuthority('library:author:query')")
    public Result<PageResult<AuthorVO>> getAuthorPage(@Valid AuthorQuery query) {
        logOperation("分页查询作者", query);
        try {
            PageResult<AuthorVO> result = authorQueryService.getAuthorPage(query);
            logOperationSuccess("分页查询作者", result);
            return buildPageResult(result);
        } catch (Exception e) {
            return handleBusinessException(e, "分页查询作者");
        }
    }

    @GetMapping("/{id}")
    @Operation(summary = "查询作者详情", description = "根据ID查询作者详细信息")
    @PreAuthorize("hasAuthority('library:author:query')")
    public Result<AuthorVO> getAuthorDetail(
            @Parameter(description = "作者ID", required = true) @PathVariable String id) {
        logOperation("查询作者详情", id);

        // 验证参数
        Result<Void> validation = validateId(id, "作者ID");
        if (!validation.isSuccess()) {
            return buildParamErrorResult("作者ID不能为空");
        }

        try {
            AuthorVO result = authorQueryService.getAuthorDetail(id);
            if (result == null) {
                return buildNotFoundResult("作者不存在");
            }
            logOperationSuccess("查询作者详情", result);
            return buildSuccessResult(result);
        } catch (Exception e) {
            return handleBusinessException(e, "查询作者详情");
        }
    }

    @PostMapping
    @Operation(summary = "创建作者", description = "新增作者信息")
    @PreAuthorize("hasAuthority('library:author:create')")
    public Result<AuthorVO> createAuthor(@Valid @RequestBody AuthorCreateDTO createDTO, BindingResult bindingResult) {
        logOperation("创建作者", createDTO);

        // 验证参数
        Result<Void> validation = handleValidationErrors(bindingResult);
        if (!validation.isSuccess()) {
            return buildParamErrorResult("参数验证失败");
        }

        try {
            Result<AuthorVO> result = authorManagementService.createAuthor(createDTO);
            if (result.isSuccess()) {
                logOperationSuccess("创建作者", result.getData());
            }
            return result;
        } catch (Exception e) {
            return handleBusinessException(e, "创建作者");
        }
    }

    @PutMapping("/{id}")
    @Operation(summary = "更新作者", description = "更新作者信息")
    @PreAuthorize("hasAuthority('library:author:update')")
    public Result<AuthorVO> updateAuthor(
            @Parameter(description = "作者ID", required = true) @PathVariable String id,
            @Valid @RequestBody AuthorUpdateDTO updateDTO, BindingResult bindingResult) {
        logOperation("更新作者", id, updateDTO);

        // 验证参数
        Result<Void> idValidation = validateId(id, "作者ID");
        if (!idValidation.isSuccess()) {
            return buildParamErrorResult("作者ID不能为空");
        }

        Result<Void> validation = handleValidationErrors(bindingResult);
        if (!validation.isSuccess()) {
            return buildParamErrorResult("参数验证失败");
        }

        try {
            Result<AuthorVO> result = authorManagementService.updateAuthor(id, updateDTO);
            if (result.isSuccess()) {
                logOperationSuccess("更新作者", result.getData());
            }
            return result;
        } catch (Exception e) {
            return handleBusinessException(e, "更新作者");
        }
    }

    @DeleteMapping("/{id}")
    @Operation(summary = "删除作者", description = "根据ID删除作者")
    @PreAuthorize("hasAuthority('library:author:delete')")
    public Result<Void> deleteAuthor(
            @Parameter(description = "作者ID", required = true) @PathVariable String id) {
        logOperation("删除作者", id);

        // 验证参数
        Result<Void> validation = validateId(id, "作者ID");
        if (!validation.isSuccess()) {
            return buildParamErrorResult("作者ID不能为空");
        }

        try {
            Result<Void> result = authorManagementService.deleteAuthor(id);
            if (result.isSuccess()) {
                logOperationSuccess("删除作者", "成功");
            }
            return result;
        } catch (Exception e) {
            return handleBusinessException(e, "删除作者");
        }
    }

    @DeleteMapping("/batch")
    @Operation(summary = "批量删除作者", description = "根据ID列表批量删除作者")
    @PreAuthorize("hasAuthority('library:author:delete')")
    public Result<Void> batchDeleteAuthors(@RequestBody List<String> ids) {
        logOperation("批量删除作者", ids);

        // 验证参数
        Result<Void> validation = validateIds(ids, "作者ID列表");
        if (!validation.isSuccess()) {
            return buildParamErrorResult("作者ID列表不能为空");
        }

        try {
            Result<Void> result = authorManagementService.batchDeleteAuthors(ids);
            if (result.isSuccess()) {
                logOperationSuccess("批量删除作者", "成功");
            }
            return result;
        } catch (Exception e) {
            return handleBusinessException(e, "批量删除作者");
        }
    }

    @PutMapping("/{id}/enable")
    @Operation(summary = "启用作者", description = "将作者设置为启用状态")
    @PreAuthorize("hasAuthority('library:author:update')")
    public Result<Void> enableAuthor(
            @Parameter(description = "作者ID", required = true) @PathVariable String id) {
        logOperation("启用作者", id);

        // 验证参数
        Result<Void> validation = validateId(id, "作者ID");
        if (!validation.isSuccess()) {
            return buildParamErrorResult("作者ID不能为空");
        }

        try {
            Result<Void> result = authorManagementService.enableAuthor(id);
            if (result.isSuccess()) {
                logOperationSuccess("启用作者", "成功");
            }
            return result;
        } catch (Exception e) {
            return handleBusinessException(e, "启用作者");
        }
    }

    @PutMapping("/{id}/disable")
    @Operation(summary = "禁用作者", description = "将作者设置为禁用状态")
    @PreAuthorize("hasAuthority('library:author:update')")
    public Result<Void> disableAuthor(
            @Parameter(description = "作者ID", required = true) @PathVariable String id) {
        logOperation("禁用作者", id);

        // 验证参数
        Result<Void> validation = validateId(id, "作者ID");
        if (!validation.isSuccess()) {
            return buildParamErrorResult("作者ID不能为空");
        }

        try {
            Result<Void> result = authorManagementService.disableAuthor(id);
            if (result.isSuccess()) {
                logOperationSuccess("禁用作者", "成功");
            }
            return result;
        } catch (Exception e) {
            return handleBusinessException(e, "禁用作者");
        }
    }

    @GetMapping("/name/{name}")
    @Operation(summary = "根据姓名查询作者", description = "根据作者姓名查询作者信息")
    @PreAuthorize("hasAuthority('library:author:query')")
    public Result<List<AuthorVO>> getAuthorsByName(
            @Parameter(description = "作者姓名", required = true) @PathVariable String name) {
        logOperation("根据姓名查询作者", name);
        try {
            List<AuthorVO> result = authorQueryService.getAuthorsByName(name);
            return buildListResult(result);
        } catch (Exception e) {
            return handleBusinessException(e, "根据姓名查询作者");
        }
    }

    @GetMapping("/book/{bookId}")
    @Operation(summary = "根据图书查询作者", description = "根据图书ID查询作者列表")
    @PreAuthorize("hasAuthority('library:author:query')")
    public Result<List<AuthorVO>> getAuthorsByBookId(
            @Parameter(description = "图书ID", required = true) @PathVariable String bookId) {
        logOperation("根据图书查询作者", bookId);

        // 验证参数
        Result<Void> validation = validateId(bookId, "图书ID");
        if (!validation.isSuccess()) {
            return buildParamErrorResult("图书ID不能为空");
        }

        try {
            List<AuthorVO> result = authorQueryService.getAuthorsByBookId(bookId);
            return buildListResult(result);
        } catch (Exception e) {
            return handleBusinessException(e, "根据图书查询作者");
        }
    }

    @GetMapping("/search")
    @Operation(summary = "搜索作者", description = "根据关键词搜索作者")
    @PreAuthorize("hasAuthority('library:author:query')")
    public Result<List<AuthorVO>> searchAuthors(
            @Parameter(description = "搜索关键词", required = true) @RequestParam String keyword,
            @Parameter(description = "限制数量") @RequestParam(defaultValue = "10") Integer limit) {
        logOperation("搜索作者", keyword, limit);
        try {
            List<AuthorVO> result = authorQueryService.searchAuthors(keyword, limit);
            return buildListResult(result);
        } catch (Exception e) {
            return handleBusinessException(e, "搜索作者");
        }
    }

    @GetMapping("/hot")
    @Operation(summary = "获取热门作者", description = "获取热门作者列表")
    public Result<List<AuthorVO>> getHotAuthors(
            @Parameter(description = "限制数量") @RequestParam(defaultValue = "10") Integer limit) {
        logOperation("获取热门作者", limit);
        try {
            List<AuthorVO> result = authorQueryService.getHotAuthors(limit);
            return buildListResult(result);
        } catch (Exception e) {
            return handleBusinessException(e, "获取热门作者");
        }
    }

    @GetMapping("/productive")
    @Operation(summary = "获取高产作者", description = "获取高产作者列表")
    public Result<List<AuthorVO>> getProductiveAuthors(
            @Parameter(description = "限制数量") @RequestParam(defaultValue = "10") Integer limit) {
        logOperation("获取高产作者", limit);
        try {
            List<AuthorVO> result = authorQueryService.getProductiveAuthors(limit);
            return buildListResult(result);
        } catch (Exception e) {
            return handleBusinessException(e, "获取高产作者");
        }
    }

    // 注意：以下统计相关的方法应该移到专门的统计控制器中，这里暂时保留但使用统计服务
    // 这样做是为了遵循单一职责原则

    @PutMapping("/{id}/book-count")
    @Operation(summary = "更新作者作品数量", description = "重新统计并更新作者的作品数量")
    @PreAuthorize("hasAuthority('library:author:update')")
    public Result<Void> updateAuthorBookCount(
            @Parameter(description = "作者ID", required = true) @PathVariable String id) {
        logOperation("更新作者作品数量", id);

        // 验证参数
        Result<Void> validation = validateId(id, "作者ID");
        if (!validation.isSuccess()) {
            return buildParamErrorResult("作者ID不能为空");
        }

        try {
            // 使用统计服务接口
            return authorStatisticsService.updateAuthorBookCount(id);
        } catch (Exception e) {
            return handleBusinessException(e, "更新作者作品数量");
        }
    }

    @PutMapping("/{id}/book-count/increment")
    @Operation(summary = "增加作者作品数量", description = "增加作者的作品数量")
    @PreAuthorize("hasAuthority('library:author:update')")
    public Result<Void> incrementAuthorBookCount(
            @Parameter(description = "作者ID", required = true) @PathVariable String id) {
        logOperation("增加作者作品数量", id);

        // 验证参数
        Result<Void> validation = validateId(id, "作者ID");
        if (!validation.isSuccess()) {
            return buildParamErrorResult("作者ID不能为空");
        }

        try {
            // 使用统计服务接口
            return authorStatisticsService.incrementAuthorBookCount(id);
        } catch (Exception e) {
            return handleBusinessException(e, "增加作者作品数量");
        }
    }

    @PutMapping("/{id}/book-count/decrement")
    @Operation(summary = "减少作者作品数量", description = "减少作者的作品数量")
    @PreAuthorize("hasAuthority('library:author:update')")
    public Result<Void> decrementAuthorBookCount(
            @Parameter(description = "作者ID", required = true) @PathVariable String id) {
        logOperation("减少作者作品数量", id);

        // 验证参数
        Result<Void> validation = validateId(id, "作者ID");
        if (!validation.isSuccess()) {
            return buildParamErrorResult("作者ID不能为空");
        }

        try {
            // 使用统计服务接口
            return authorStatisticsService.decrementAuthorBookCount(id);
        } catch (Exception e) {
            return handleBusinessException(e, "减少作者作品数量");
        }
    }

    @PutMapping("/{id}/borrow-count")
    @Operation(summary = "更新作者总借阅次数", description = "重新统计并更新作者的总借阅次数")
    @PreAuthorize("hasAuthority('library:author:update')")
    public Result<Void> updateAuthorTotalBorrowCount(
            @Parameter(description = "作者ID", required = true) @PathVariable String id) {
        logOperation("更新作者总借阅次数", id);

        // 验证参数
        Result<Void> validation = validateId(id, "作者ID");
        if (!validation.isSuccess()) {
            return buildParamErrorResult("作者ID不能为空");
        }

        try {
            // 使用统计服务接口
            return authorStatisticsService.updateAuthorTotalBorrowCount(id);
        } catch (Exception e) {
            return handleBusinessException(e, "更新作者总借阅次数");
        }
    }

    @PutMapping("/{id}/borrow-count/increment")
    @Operation(summary = "增加作者总借阅次数", description = "增加作者的总借阅次数")
    @PreAuthorize("hasAuthority('library:author:update')")
    public Result<Void> incrementAuthorTotalBorrowCount(
            @Parameter(description = "作者ID", required = true) @PathVariable String id) {
        logOperation("增加作者总借阅次数", id);

        // 验证参数
        Result<Void> validation = validateId(id, "作者ID");
        if (!validation.isSuccess()) {
            return buildParamErrorResult("作者ID不能为空");
        }

        try {
            // 使用统计服务接口
            return authorStatisticsService.incrementAuthorTotalBorrowCount(id);
        } catch (Exception e) {
            return handleBusinessException(e, "增加作者总借阅次数");
        }
    }

    @GetMapping("/check/name/{name}")
    @Operation(summary = "检查作者姓名", description = "检查作者姓名是否已存在")
    @PreAuthorize("hasAuthority('library:author:query')")
    public Result<Boolean> checkAuthorName(
            @Parameter(description = "作者姓名", required = true) @PathVariable String name,
            @Parameter(description = "排除的作者ID") @RequestParam(required = false) String excludeId) {
        logOperation("检查作者姓名", name, excludeId);
        try {
            boolean exists = authorQueryService.existsByName(name, excludeId);
            return buildSuccessResult(!exists);
        } catch (Exception e) {
            return handleBusinessException(e, "检查作者姓名");
        }
    }

    @PostMapping("/import")
    @Operation(summary = "导入作者数据", description = "批量导入作者数据")
    @PreAuthorize("hasAuthority('library:author:import')")
    public Result<String> importAuthors(@RequestBody List<AuthorCreateDTO> authors) {
        logOperation("导入作者数据", authors.size());

        // 验证参数
        if (authors == null || authors.isEmpty()) {
            return buildParamErrorResult("导入数据不能为空");
        }

        try {
            Result<String> result = authorImportExportService.importAuthors(authors);
            if (result.isSuccess()) {
                logOperationSuccess("导入作者数据", result.getData());
            }
            return result;
        } catch (Exception e) {
            return handleBusinessException(e, "导入作者数据");
        }
    }

    @GetMapping("/export")
    @Operation(summary = "导出作者数据", description = "导出作者数据到Excel文件")
    @PreAuthorize("hasAuthority('library:author:export')")
    public Result<String> exportAuthors(@Valid AuthorQuery query) {
        logOperation("导出作者数据", query);
        try {
            Result<String> result = authorImportExportService.exportAuthors(query);
            if (result.isSuccess()) {
                logOperationSuccess("导出作者数据", result.getData());
            }
            return result;
        } catch (Exception e) {
            return handleBusinessException(e, "导出作者数据");
        }
    }
}
